package com.book.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.IService;
import com.book.core.mode.R;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

@Data
@Slf4j
public class GenericExcelDataListener<T> implements ReadListener<T> {

    // 批处理大小
    private static final int BATCH_COUNT = 100;
    // 数据库Repository
    private final IService<T> repository;
    // 缓存的数据
    private List<T> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

    // 成功计数
    private int successCount = 0;

    // 失败计数
    private int failCount = 0;

    // 错误信息
    private StringBuilder errorMessages = new StringBuilder();

    /**
     * 构造函数
     *
     * @param repository 数据库Repository
     */


    public GenericExcelDataListener(IService<T> repository) {
        this.repository = repository;
    }

    @Override
    public void invoke(T data, AnalysisContext context) {
        log.info("解析到一条数据:{}", JSON.toJSONString(data));
        try {
            // 数据校验可以在这里添加
            validateData(data);
            cachedDataList.add(data);
            if (cachedDataList.size() >= BATCH_COUNT) {
                saveData();
                cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
            }
        } catch (Exception e) {
            failCount++;
            errorMessages.append("第").append(context.readRowHolder().getRowIndex() + 1)
                    .append("行数据错误：").append(e.getMessage()).append("\n");
            log.error("数据解析失败", e);
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        if (!cachedDataList.isEmpty()) {
            saveData();
        }
        log.info("所有数据解析完成！成功: {} 条，失败: {} 条", successCount, failCount);
    }

    /**
     * 保存数据到数据库
     */
    private void saveData() {
        log.info("{}条数据，开始存储数据库！", cachedDataList.size());
        try {
            repository.saveBatch(cachedDataList);
            successCount += cachedDataList.size();
            log.info("存储数据库成功！");
        } catch (Exception e) {
            failCount += cachedDataList.size();
            errorMessages.append("批量保存失败：").append(e.getMessage()).append("\n");
            log.error("存储数据库失败", e);
        }
    }

    /**
     * 数据校验方法，子类可以重写
     *
     * @param data Excel数据
     * @throws Exception 校验不通过时抛出异常
     */
    protected void validateData(T data) throws Exception {
        // 默认不进行校验，子类可以重写此方法实现特定校验逻辑
    }
}
